`include "PRV564Config.v"
`include "PRV564Define.v"
//////////////////////////////////////////////////////////////////////////////////////////////////
//  Date    : 2021                                                                              //
//  Author  : Jack.Pan                                                                          //
//  Desc    : Write Back Secect Unit for prv564 processor                                       //
//  Version : 0.1(Verision 0.1 ，加入了冲刷信号)                                                 //
//////////////////////////////////////////////////////////////////////////////////////////////////
module WB_select(
    input wire              Global_Flush,
//-------------------pipline 0 input--------------------------
    input  wire             PIP0i_MSC_valid,
    input  wire             PIP0i_MSC_LoadPageFlt,
    input  wire             PIP0i_MSC_LoadAccFlt,
    input  wire             PIP0i_MSC_LoadAddrMis,
    input  wire             PIP0i_MSC_StorePageFlt,
    input  wire             PIP0i_MSC_StoreAccFlt,
    input  wire             PIP0i_MSC_StoreAddrMis,
    input  wire             PIP0i_INFO_ci,
    input  wire [7:0]       PIP0i_INFO_itag,
    input  wire [`XLEN-1:0] PIP0i_INFO_pc,
    input  wire [1:0]       PIP0i_INFO_priv,
    input  wire [`XLEN-1:0] PIP0i_DATA_data1,
    input  wire [`XLEN-1:0] PIP0i_DATA_data2,
    output  reg             PIP0o_FC_ready,
//------------------pipline 1 input-----------------------------
    input  wire             PIP1i_MSC_valid,
    input  wire             PIP1i_MSC_LoadPageFlt,
    input  wire             PIP1i_MSC_LoadAccFlt,
    input  wire             PIP1i_MSC_LoadAddrMis,
    input  wire             PIP1i_MSC_StorePageFlt,
    input  wire             PIP1i_MSC_StoreAccFlt,
    input  wire             PIP1i_MSC_StoreAddrMis,
    input  wire             PIP1i_INFO_ci,
    input  wire [7:0]       PIP1i_INFO_itag,
    input  wire [`XLEN-1:0] PIP1i_INFO_pc,
    input  wire [1:0]       PIP1i_INFO_priv,
    input  wire [`XLEN-1:0] PIP1i_DATA_data1,
    input  wire [`XLEN-1:0] PIP1i_DATA_data2,
    output  reg             PIP1o_FC_ready,
//------------------pipline 2 input-----------------------------
    input  wire             PIP2i_MSC_valid,
    input  wire             PIP2i_MSC_LoadPageFlt,
    input  wire             PIP2i_MSC_LoadAccFlt,
    input  wire             PIP2i_MSC_LoadAddrMis,
    input  wire             PIP2i_MSC_StorePageFlt,
    input  wire             PIP2i_MSC_StoreAccFlt,
    input  wire             PIP2i_MSC_StoreAddrMis,
    input  wire             PIP2i_INFO_ci,
    input  wire [7:0]       PIP2i_INFO_itag,
    input  wire [`XLEN-1:0] PIP2i_INFO_pc,
    input  wire [1:0]       PIP2i_INFO_priv,
    input  wire [`XLEN-1:0] PIP2i_DATA_data1,
    input  wire [`XLEN-1:0] PIP2i_DATA_data2,
    output  reg             PIP2o_FC_ready,
//-------------------DITF read port------------------------------
    input  wire             DITFo_v,                    //current entry is valid
    input  wire [7:0]       DITFo_itag,                 //当前待写回指令的tag
//  input  wire [4:0]       DITFo_rs1index,             //Not use
//  input  wire             DITFo_rs1en,
//  input  wire [4:0]       DITFo_rs2index,
//  input  wire             DITFo_rs2en,
    input  wire [4:0]       DITFo_rdindex,
    input  wire             DITFo_rden,                 //GPR 写回使能
    input  wire [11:0]      DITFo_csrindex,
    input  wire             DITFo_csren,                //CSR 写回使能
    input  wire             DITFo_jmp,
    input  wire             DITFo_InsAccessFlt,
    input  wire             DITFo_InsPageFlt,
    input  wire             DITFo_InsAddrMis,
    input  wire             DITFo_illins,
    input  wire             DITFo_mret,
    input  wire             DITFo_sret,
    input  wire             DITFo_ecall,
    input  wire             DITFo_ebreak,
    input  wire             DITFo_fence,
    input  wire             DITFo_fencei,
    input  wire             DITFo_fencevma,
    input  wire             DITFo_system,
    output  reg             DITFi_remove,               //从DITF中移除表项
//---------------------To write back---------------------
    output  reg             WB_valid,
    output  reg             WB_rden,
    output  reg [4:0]       WB_rdindex,
    output  reg [`XLEN-1:0] WB_data1,
    output  reg             WB_csren,
    output  reg [11:0]      WB_csrindex,
    output  reg [`XLEN-1:0] WB_data2,
    output  reg [`XLEN-1:0] WB_pc,                      //当前正在写回的PC
	output  reg [1:0]       WB_priv,
    output  reg             WB_ci,
    output  reg             WB_jmp,
    output  reg             WB_InsAccFlt,
    output  reg             WB_InsPageFlt,
    output  reg             WB_InsAddrMis,
    output  reg             WB_LoadAccFlt,
    output  reg             WB_LoadPageFlt,
    output  reg             WB_LoadAddrMis,
    output  reg             WB_StoreAccFlt,
    output  reg             WB_StorePageFlt,
    output  reg             WB_StoreAddrMis,
    output  reg             WB_illins,
    output  reg             WB_mret,
    output  reg             WB_sret,
    output  reg             WB_ecall,
    output  reg             WB_ebreak,
    output  reg             WB_fence,
    output  reg             WB_fencei,
    output  reg             WB_fencevma,
    output  reg             WB_system
);

always@(*)begin
    if(Global_Flush)begin
        WB_valid        = 1'b0;
        WB_rden         = 1'b0;
        WB_rdindex      = 5'h00;
        WB_data1        = 64'hx;
        WB_csren        = 1'b0;  
        WB_csrindex     = 12'h000;
        WB_data2        = 64'hx;
        WB_pc           = 64'h0;                               //当前正在写回的PC
        WB_priv         = `Machine;
        WB_jmp          = 1'b0;
        WB_ci           = 1'b0;
        WB_InsAccFlt    = 1'b0;
        WB_InsPageFlt   = 1'b0;
        WB_InsAddrMis   = 1'b0;
        WB_LoadAccFlt   = 1'b0;
        WB_LoadPageFlt  = 1'b0;
        WB_LoadAddrMis  = 1'b0;
        WB_StoreAccFlt  = 1'b0;
        WB_StorePageFlt = 1'b0;
        WB_StoreAddrMis = 1'b0;
        WB_illins       = 1'b0;
        WB_mret         = 1'b0;
        WB_sret         = 1'b0;
        WB_ecall        = 1'b0;
        WB_ebreak       = 1'b0;
        WB_fence        = 1'b0;
        WB_fencei       = 1'b0;
        WB_fencevma     = 1'b0;
        WB_system       = 1'b0;
        DITFi_remove    = 1'b0;
        PIP0o_FC_ready  = PIP0i_MSC_valid;
        PIP1o_FC_ready  = PIP1i_MSC_valid;
        PIP2o_FC_ready  = PIP2i_MSC_valid;
    end
    else if(PIP0i_MSC_valid & DITFo_v & (DITFo_itag == PIP0i_INFO_itag))begin    //管线0指令写回
        WB_valid        = 1'b1;
        WB_rden         = (PIP0i_MSC_LoadAccFlt | PIP0i_MSC_LoadPageFlt | PIP0i_MSC_LoadAddrMis | PIP0i_MSC_StoreAccFlt | PIP0i_MSC_StoreAddrMis | PIP0i_MSC_StorePageFlt) ? 1'b0 : DITFo_rden;
        WB_rdindex      = DITFo_rdindex;
        WB_data1        = PIP0i_DATA_data1;
        WB_csren        = DITFo_csren;  
        WB_csrindex     = DITFo_csrindex;
        WB_data2        = PIP0i_DATA_data2;
        WB_pc           = PIP0i_INFO_pc;                      //当前正在写回的PC
        WB_priv         = PIP0i_INFO_priv;
        WB_jmp          = DITFo_jmp;
        WB_ci           = PIP0i_INFO_ci;
        WB_InsAccFlt    = DITFo_InsAccessFlt;
        WB_InsPageFlt   = DITFo_InsPageFlt;
        WB_InsAddrMis   = DITFo_InsAddrMis;
        WB_LoadAccFlt   = PIP0i_MSC_LoadAccFlt;
        WB_LoadPageFlt  = PIP0i_MSC_LoadPageFlt;
        WB_LoadAddrMis  = PIP0i_MSC_LoadAddrMis;
        WB_StoreAccFlt  = PIP0i_MSC_StoreAccFlt;
        WB_StorePageFlt = PIP0i_MSC_StorePageFlt;
        WB_StoreAddrMis = PIP0i_MSC_StoreAddrMis;
        WB_illins       = DITFo_illins;
        WB_mret         = DITFo_mret;
        WB_sret         = DITFo_sret;
        WB_ecall        = DITFo_ecall;
        WB_ebreak       = DITFo_ebreak;
        WB_fence        = DITFo_fence;
        WB_fencei       = DITFo_fencei;
        WB_fencevma     = DITFo_fencevma;
        WB_system       = DITFo_system;
        DITFi_remove    = 1'b1;                                //允许移除表项
        PIP0o_FC_ready  = 1'b1;                                //管线0允许写回
        PIP1o_FC_ready  = 1'b0;
        PIP2o_FC_ready  = 1'b0;                                
    end
    else if(PIP1i_MSC_valid & DITFo_v & (DITFo_itag == PIP1i_INFO_itag))begin  //管线1指令写回
        WB_valid        = 1'b1;
        WB_rden         = (PIP1i_MSC_LoadAccFlt | PIP1i_MSC_LoadPageFlt | PIP1i_MSC_LoadAddrMis | PIP1i_MSC_StoreAccFlt | PIP1i_MSC_StoreAddrMis | PIP1i_MSC_StorePageFlt) ? 1'b0 : DITFo_rden;
        WB_rdindex      = DITFo_rdindex;
        WB_data1        = PIP1i_DATA_data1;
        WB_csren        = DITFo_csren;  
        WB_csrindex     = DITFo_csrindex;
        WB_data2        = PIP1i_DATA_data2;
        WB_pc           = PIP1i_INFO_pc;                      //当前正在写回的PC
        WB_priv         = PIP1i_INFO_priv;
        WB_jmp          = DITFo_jmp;
        WB_ci           = PIP1i_INFO_ci;
        WB_InsAccFlt    = DITFo_InsAccessFlt;
        WB_InsPageFlt   = DITFo_InsPageFlt;
        WB_InsAddrMis   = DITFo_InsAddrMis;
        WB_LoadAccFlt   = PIP1i_MSC_LoadAccFlt;
        WB_LoadPageFlt  = PIP1i_MSC_LoadPageFlt;
        WB_LoadAddrMis  = PIP1i_MSC_LoadAddrMis;
        WB_StoreAccFlt  = PIP1i_MSC_StoreAccFlt;
        WB_StorePageFlt = PIP1i_MSC_StorePageFlt;
        WB_StoreAddrMis = PIP1i_MSC_StoreAddrMis;
        WB_illins       = DITFo_illins;
        WB_mret         = DITFo_mret;
        WB_sret         = DITFo_sret;
        WB_ecall        = DITFo_ecall;
        WB_ebreak       = DITFo_ebreak;
        WB_fence        = DITFo_fence;
        WB_fencei       = DITFo_fencei;
        WB_fencevma     = DITFo_fencevma;
        WB_system       = DITFo_system;
        DITFi_remove    = 1'b1;                                //允许移除表项
        PIP0o_FC_ready  = 1'b0;                                
        PIP1o_FC_ready  = 1'b1;                                //管线1允许写回
        PIP2o_FC_ready  = 1'b0;   
    end
    else if(PIP2i_MSC_valid & DITFo_v & (DITFo_itag == PIP2i_INFO_itag))begin  //管线1指令写回
        WB_valid        = 1'b1;
        WB_rden         = (PIP2i_MSC_LoadAccFlt | PIP2i_MSC_LoadPageFlt | PIP2i_MSC_LoadAddrMis | PIP2i_MSC_StoreAccFlt | PIP2i_MSC_StoreAddrMis | PIP2i_MSC_StorePageFlt) ? 1'b0 : DITFo_rden;
        WB_rdindex      = DITFo_rdindex;
        WB_data1        = PIP2i_DATA_data1;
        WB_csren        = DITFo_csren;  
        WB_csrindex     = DITFo_csrindex;
        WB_data2        = PIP2i_DATA_data2;
        WB_pc           = PIP2i_INFO_pc;                      //当前正在写回的PC
        WB_priv         = PIP2i_INFO_priv;
        WB_jmp          = DITFo_jmp;
        WB_ci           = PIP2i_INFO_ci;
        WB_InsAccFlt    = DITFo_InsAccessFlt;
        WB_InsPageFlt   = DITFo_InsPageFlt;
        WB_InsAddrMis   = DITFo_InsAddrMis;
        WB_LoadAccFlt   = PIP2i_MSC_LoadAccFlt;
        WB_LoadPageFlt  = PIP2i_MSC_LoadPageFlt;
        WB_LoadAddrMis  = PIP2i_MSC_LoadAddrMis;
        WB_StoreAccFlt  = PIP2i_MSC_StoreAccFlt;
        WB_StorePageFlt = PIP2i_MSC_StorePageFlt;
        WB_StoreAddrMis = PIP2i_MSC_StoreAddrMis;
        WB_illins       = DITFo_illins;
        WB_mret         = DITFo_mret;
        WB_sret         = DITFo_sret;
        WB_ecall        = DITFo_ecall;
        WB_ebreak       = DITFo_ebreak;
        WB_fence        = DITFo_fence;
        WB_fencei       = DITFo_fencei;
        WB_fencevma     = DITFo_fencevma;
        WB_system       = DITFo_system;
        DITFi_remove    = 1'b1;                                //允许移除表项
        PIP0o_FC_ready  = 1'b0;                                
        PIP1o_FC_ready  = 1'b0;
        PIP2o_FC_ready  = 1'b1;   
    end
    else begin
        WB_valid        = 1'b0;
        WB_rden         = 1'b0;
        WB_rdindex      = 5'h00;
        WB_data1        = 64'hx;
        WB_csren        = 1'b0;  
        WB_csrindex     = 12'h000;
        WB_data2        = 64'hx;
        WB_pc           = 64'h0;                               //当前正在写回的PC
        WB_priv         = `Machine;
        WB_jmp          = 1'b0;
        WB_ci           = 1'b0;
        WB_InsAccFlt    = 1'b0;
        WB_InsPageFlt   = 1'b0;
        WB_InsAddrMis   = 1'b0;
        WB_LoadAccFlt   = 1'b0;
        WB_LoadPageFlt  = 1'b0;
        WB_LoadAddrMis  = 1'b0;
        WB_StoreAccFlt  = 1'b0;
        WB_StorePageFlt = 1'b0;
        WB_StoreAddrMis = 1'b0;
        WB_illins       = 1'b0;
        WB_mret         = 1'b0;
        WB_sret         = 1'b0;
        WB_ecall        = 1'b0;
        WB_ebreak       = 1'b0;
        WB_fence        = 1'b0;
        WB_fencei       = 1'b0;
        WB_fencevma     = 1'b0;
        WB_system       = 1'b0;
        DITFi_remove    = 1'b0;
        PIP0o_FC_ready  = 1'b0;
        PIP1o_FC_ready  = 1'b0;
        PIP2o_FC_ready  = 1'b0;   
    end
end

endmodule

